package com.happe.foodeasy.helper;

import org.apache.commons.beanutils.BasicDynaBean;
import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.DynaProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.PreparedStatementSetter;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * this class is used to parse object's property for data stores.
 * Created by wubin on 2016-05-02.
 */
public class DaoHelper<T> {
    private Map<String, Object> params = new HashMap<>();

    public DaoHelper() {
    }

    public String parseTableName(Class<T> targetClass) {
        return targetClass.getSimpleName();
    }

    public Map<String, Object> parseParams(T targetEntity, Class<T> targetClassName) {
        DealRelationalAnnotationWrapper<T> deal = new DealRelationalAnnotationWrapper<>(targetClassName, targetEntity);
        try {
            deal.startDeal();
        } catch (Exception e) {
            e.printStackTrace();
        }
        BasicDynaClass resultClass = deal.retrieveDealClass();
        BasicDynaBean resultObject = deal.retrieveDealBean();
        DynaProperty[] dynaProperties = resultClass.getDynaProperties();
        for (DynaProperty property : dynaProperties) {
            params.put(property.getName(), resultObject.get(property.getName()));
        }

        return params;
    }

    public PreparedStatementSetter createStatementSetter() {
        class CustomStatementSetter implements PreparedStatementSetter {
            private Map<String, Object> params;

            private CustomStatementSetter(Map<String, Object> params) {
                this.params = params;
            }

            @Override
            public void setValues(PreparedStatement ps) throws SQLException {
                int i = 1;
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    String key = entry.getKey();
                    Object value = params.get(key);
                    if (ClassOperateHelper.checkTargetClassIsByteArray(value.getClass())) {
                        ps.setBytes(i, (byte[]) value);
                    } else if (ClassOperateHelper.checkTargetClassIsBoolean(value.getClass())) {
                        String result = (Boolean) value ? "0" : "1";
                        ps.setString(i, result);
                    } else {
                        ps.setObject(i, value);
                    }
                    i++;
                }
            }
        }
        return new CustomStatementSetter(params);
    }

    public static Connection retrieveConnection() throws SQLException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        DataSource source = (DataSource) context.getBean("dataSource");
        return source.getConnection();
    }
}
